package com.slipper.login.controller;

import com.slipper.common.bo.UserDetail;
import com.slipper.constants.Constants;
import com.slipper.core.gson.GsonUtil;
import com.slipper.login.LoginFactory;
import com.slipper.system.employee.bo.EmployeeBO;
import com.slipper.system.employee.service.EmployeeService;
import com.slipper.system.license.bo.LicenseBO;
import com.slipper.system.license.service.LicenseService;
import com.slipper.system.log.bo.LoginLogBO;
import com.slipper.system.log.controller.LogAsyncService;
import com.slipper.system.organization.bo.OrganizationBO;
import com.slipper.system.organization.service.OrganizationService;
import com.slipper.system.role.bo.RoleBO;
import com.slipper.system.role.bo.RolePrivilegeBO;
import com.slipper.system.role.service.RolePrivilegeService;
import com.slipper.system.role.service.RoleService;
import com.slipper.system.setting.bo.SettingBO;
import com.slipper.system.setting.service.SettingService;
import com.slipper.util.*;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.slipper.login.LoginType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping()
public class LoginController {
    @Resource
    private RoleService roleService;
    @Resource
    private EmployeeService employeeService;
    @Resource
    private OrganizationService organizationService;
    @Resource
    private SettingService settingService;
    @Resource
    private RolePrivilegeService rolePrivilegeService;
    @Resource
    private LogAsyncService logAsyncService;
    @Resource
    private LicenseService licenseService;

    @PostMapping("/login")
    public String login(HttpServletRequest request, @RequestBody EmployeeBO bo) {
        long startTime = System.currentTimeMillis();
        LicenseBO license = licenseService.queryBy();
        if (!license.isValid()) {
            return ResultUtil.failureResult("授权已到期，请更新授权码！");
        }
        if (Tool.isBlank(bo.getUsername()) || Tool.isBlank(bo.getPassword())) {
            return ResultUtil.failureResult("用户名/密码不能为空！");
        } else {
            bo.setUsername(bo.getUsername().trim());
            bo.setPassword(bo.getPassword().trim());
        }

        SettingBO setting = settingService.querySetting();
        String clientFlag = request.getHeader("Client-Flag");
        if (!"app".equals(clientFlag)
                && Constants.YES.equals(setting.getLoginCaptcha())
                && (Tool.isBlank(bo.getCaptcha()) || !bo.getCaptcha().equalsIgnoreCase(Constants.getAndCleanCaptcha()))) {
            return ResultUtil.failureResult("验证码不正确！");
        }

        EmployeeBO employee = this.employeeService.queryByLogin(bo);
        if (employee == null) {
            return ResultUtil.failureResult("用户名错误！");
        }

        if (!MD5.encodePwd(bo.getPassword()).equals(employee.getPassword())) {
            return ResultUtil.failureResult("密码错误！");
        }

        return doLogin(request, employee, setting, startTime);
    }

    @PostMapping("/tokenLogin")
    public String tokenLogin(HttpServletRequest request, @RequestBody Map<String, Object> paramMap) {
        String token = (String) paramMap.get("token");
        if (Tool.isBlank(token)) {
            return ResultUtil.failureResult("登录失败！");
        }

        try {

            long startTime = System.currentTimeMillis();
            UserDetail user = GsonUtil.fromJson(JwtUtil.parserToken(AESUtil.decrypt(token)), UserDetail.class);
            SettingBO setting = settingService.querySetting();
            return doLogin(request, employeeService.queryBy(user.getEmployeeId()), setting, startTime);
        } catch (Exception e) {
            return ResultUtil.failureResult("登录失败！");
        }
    }

    @PostMapping("/ssoLogin")
    public String ssoLogin(HttpServletRequest request, @RequestBody Map<String, Object> paramMap) {
        long startTime = System.currentTimeMillis();
        SettingBO setting = settingService.querySetting();
        if (Tool.isBlank(setting.getSsoScriptId())) return ResultUtil.failureResult("未配置单点登录脚本！");

        paramMap.put("groovyScriptId", setting.getSsoScriptId());
        Object object = LoginFactory.login(LoginType.GROOVY, paramMap);
        if (Tool.isBlank(object)) {
            return ResultUtil.failureResult("登录失败！");
        }

        return doLogin(request, employeeService.queryBy(object.toString()), setting, startTime);
    }

    private String doLogin(HttpServletRequest request, EmployeeBO employee, SettingBO setting, long startTime) {
        if (employee == null) return ResultUtil.failureResult("用户不存在！");

        if (setting == null) {
            setting = settingService.querySetting();
        }

        // 判断密码是否过期
        boolean isSuperAdmin = this.roleService.isSuperAdmin(employee.getId());
        if (!isSuperAdmin
                && Constants.YES.equals(setting.getPasswordCheck())
                && setting.getPasswordDay() != null
                && setting.getPasswordDay() > 0
                && (employee.getPasswordTime() == null
                    || DateUtil.dayDiff(employee.getPasswordTime(), System.currentTimeMillis()) > setting.getPasswordDay())) {
            return ResultUtil.failureResult("密码已过期，请联系管理员进行修改！");
        }

        employee.setPassword(null);
        employee.setLoginIp(Tool.getIpAddr(request));
        employee.setLoginTime(System.currentTimeMillis());
        employee.setSuperAdmin(isSuperAdmin);

        UserDetail userDetail = new UserDetail();
        userDetail.setClientFlag(request.getHeader("Client-Flag"));
        userDetail.setEmployee(employee);
        userDetail.setSuperAdmin(isSuperAdmin);
        userDetail.setUser(BeanUtil.toLowerCaseKey(employeeService.queryMapData(employee.getId())));
        userDetail.getUser().remove("password");

        OrganizationBO organization;
        if (isSuperAdmin) {
            organization = new OrganizationBO();
            organization.setId(Constants.ROOT_ID);
        } else {
            organization = organizationService.queryBy(employee.getOrganizationId());
        }

        OrganizationBO organizationQO = new OrganizationBO();
        organizationQO.setEmployeeId(employee.getId());
        List<OrganizationBO> orgList = organizationService.queryList(organizationQO);

        if (organization == null && orgList.isEmpty() && userDetail.isPC()) {
            return ResultUtil.failureResult("账号未配置部门，请先配置！");
        }

        if (organization == null && !orgList.isEmpty()) {
            organization = orgList.getFirst();
            employee.setOrganizationId(organization.getId());
            employeeService.updateOrganization(employee);
        }

        if (organization != null) {
            OrganizationBO unit = organizationService.queryUnit(organization.getId());
            employee.setUnitId(unit == null ? null : unit.getId());
            employee.setOrganizationList(orgList);
            employee.setOrgId(organization.getId());
            employee.setOrgName(organization.getName());
            userDetail.setUnitId(unit == null ? null : unit.getId());
            userDetail.setOrganization(organization);
            userDetail.setOrg(BeanUtil.toLowerCaseKey(organizationService.queryMapData(organization.getId())));
            userDetail.getUser().put("fullId", organization.getId() + "@" + userDetail.getEmployeeId());
        }

        if (userDetail.isPC()) {
            RoleBO roleQO = new RoleBO();
            roleQO.setEmployeeId(employee.getId());
            List<RoleBO> roleList = this.roleService.queryList(roleQO);
            if (roleList.isEmpty()) {
                return ResultUtil.failureResult("账号未配置角色，请先配置！");
            }
            userDetail.setRoleList(roleList);

            if (!isSuperAdmin) {
                RolePrivilegeBO rolePrivilegeQO = new RolePrivilegeBO();
                rolePrivilegeQO.setEmployeeId(employee.getId());
                userDetail.setPrivilegeList(rolePrivilegeService.queryList(rolePrivilegeQO));
            }
        }

        Constants.setSessionUser(userDetail);

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("user", employee);
        dataMap.put("userData", userDetail.getUser());
        dataMap.put("orgData", userDetail.getOrg());
        dataMap.put("dateData", DateUtil.currDate());
        if (userDetail.isApp()) {
            String token = JwtUtil.generateToken(GsonUtil.toJson(userDetail), 30);
            dataMap.put("token", AESUtil.encrypt(token));
        } else {
            dataMap.put("token", Tool.getUUID());
        }

        LoginLogBO loginLog = new LoginLogBO();
        loginLog.setOrgId(userDetail.getOrgId());
        loginLog.setOrgName(userDetail.getOrgName());
        loginLog.setUserId(employee.getId());
        loginLog.setUserName(employee.getName());
        loginLog.setLoginTime(startTime);
        loginLog.setIpAddress(employee.getLoginIp());
        loginLog.setBrowserInfo(request.getHeader("User-Agent"));
        loginLog.setLoginType(userDetail.getClientFlag());
        loginLog.setOperateInfo("登录成功！");
        loginLog.setTakeTime(System.currentTimeMillis() - startTime);
        logAsyncService.saveLoginLog(loginLog);
        return ResultUtil.successResult("登录成功！", dataMap);
    }

    @PostMapping("/logout")
    public String logout(HttpServletRequest request) {
        long startTime = System.currentTimeMillis();
        UserDetail userDetail = Constants.getCurrentUser(false);
        if (userDetail == null) return ResultUtil.failureResult("未登录！");

        LoginLogBO loginLog = new LoginLogBO();
        loginLog.setOrgId(userDetail.getOrgId());
        loginLog.setOrgName(userDetail.getOrgName());
        loginLog.setUserId(userDetail.getEmployee().getId());
        loginLog.setUserName(userDetail.getEmployee().getName());
        loginLog.setLoginTime(startTime);
        loginLog.setIpAddress(Tool.getIpAddr(request));
        loginLog.setLoginType(userDetail.getClientFlag());
        loginLog.setBrowserInfo(request.getHeader("User-Agent"));
        loginLog.setOperateInfo("退出登录！");
        loginLog.setTakeTime(System.currentTimeMillis() - startTime);
        this.logAsyncService.saveLoginLog(loginLog);

        Constants.getCurrentRequest().getSession().invalidate();
        return ResultUtil.successResult("退出登录成功！");
    }
}
